#ifndef __M_SESSION_H__
#define __M_SESSION_H__

#include "room.hpp"

typedef enum {UNLOGIN ,LOGIN} ss_statu;
class session
{
private:
    uint64_t _ssid;
    uint64_t _uid;
    ss_statu _statu;
    wsserver_t::timer_ptr _tp;
public:
    session(uint64_t ssid):_ssid(ssid)   { DLOG("SESSION %p 被创建！",this); }
    ~session() { DLOG("SESSION %p 被释放！",this); }
    void set_user(uint64_t uid) {_uid = uid;}
    void set_statu(ss_statu statu) { _statu = statu;}
    uint64_t ssid() { return _ssid;}
    uint64_t get_user() { return _uid;}
    bool is_login() { return (_statu == LOGIN);}
    void set_timer(const wsserver_t::timer_ptr &tp) {_tp = tp;}
    wsserver_t::timer_ptr& get_timer() { return _tp;}
};

using session_ptr = std::shared_ptr<session>;

#define SESSION_TIMEOUT 30000
#define SESSION_FOREVER -1

class session_manager
{
private:
    uint64_t _next_ssid;
    std::mutex _mutex;
    std::unordered_map<uint64_t,session_ptr> _session;
    wsserver_t *_server;
public:
    session_manager(wsserver_t *srv): _next_ssid(1),_server(srv)
    {
        DLOG("session管理器初始化完毕！");
    }
    ~session_manager()
    {
        DLOG("session管理器即将销毁！");
    }
    session_ptr create_session(uint64_t uid,ss_statu statu)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        session_ptr ssp(new session(_next_ssid));
        ssp->set_statu(statu);
        ssp->set_user(uid);
        _session.insert(std::make_pair(_next_ssid,ssp));
        _next_ssid++;
        return ssp;
    }
    session_ptr get_session_by_ssid(uint64_t ssid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _session.find(ssid);
        if(it == _session.end())
        {
            return session_ptr();
        }
        return it->second;
    }
    void append_session(const session_ptr &ssp)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _session.insert(std::make_pair(ssp->ssid(),ssp));
    }
    void remove_session(uint64_t ssid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _session.erase(ssid);
    }
    void set_session_expire_time(uint64_t ssid, int ms)
    {
        session_ptr ssp = get_session_by_ssid(ssid);
        if(ssp.get() == nullptr)
        {
            return ;
        }
        wsserver_t::timer_ptr tp = ssp->get_timer(); 
        if(tp.get() == nullptr && ms == SESSION_FOREVER)
        {
            //1.在session永久存在的情况下，设置永久存在
            return ;
        }else if(tp.get() == nullptr && ms != SESSION_FOREVER)
        {
            //2.在session永久存在的情况下，设置指定时间之后被删除的定时任务
            wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms,
                std::bind(&session_manager::remove_session,this,ssid));
            ssp->set_timer(tmp_tp);
        }else if(tp.get() != nullptr && ms == SESSION_FOREVER)
        {
            //3.在session设置了定时删除的情况下，将session设置为永久存在
            tp->cancel();//取消定时任务并不是立即执行
            //重新给session管理器中添加session信息，添加的时候使用定时器，不是立即添加
            ssp->set_timer(wsserver_t::timer_ptr());
            _server->set_timer(0,std::bind(&session_manager::append_session,this,ssp));
        }else if(tp.get() != nullptr && ms != SESSION_FOREVER)
        {
            //4.在session设置的定时删除的情况下，将session重置删除时间
            tp->cancel();//取消定时任务并不是立即执行
            ssp->set_timer(wsserver_t::timer_ptr());
            _server->set_timer(0,std::bind(&session_manager::append_session,this,ssp));
            //重新给session管理器中添加session信息，添加的时候使用定时器，不是立即添加
            wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms,
                std::bind(&session_manager::remove_session,this,ssp->ssid()));
            ssp->set_timer(tmp_tp);
        }
    }
    
};

#endif